package com.example.prompt.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class JsonUtil {
	///
    // 输出空置字段
    private static final SerializerFeature[] features = {
            SerializerFeature.IgnoreNonFieldGetter,
            SerializerFeature.WriteMapNullValue,					//是否输出值为null的字段,默认为false
            SerializerFeature.WriteNullListAsEmpty,					//List字段如果为null,输出为[],而非null
            SerializerFeature.WriteNullNumberAsZero,				//数值字段如果为null,输出为0,而非null
            SerializerFeature.WriteNullBooleanAsFalse,				//Boolean字段如果为null,输出为false,而非null
            SerializerFeature.WriteNullStringAsEmpty,				//字符类型字段如果为null,输出为"",而非null 
            SerializerFeature.DisableCircularReferenceDetect
    };

    public static byte[] marshalToBytes(Object obj) {
        return JSON.toJSONBytes(obj); // 默认为UTF-8
    }

    public static byte[] marshalToBytes(Object obj, SerializerFeature... features) {
        return JSON.toJSONBytes(obj, features); // 默认为UTF-8
    }
    
    /**
     * 可以允许指定一些过滤字段进行生成json对象
     */
    public static byte[] marshalToBytes(Object obj, List<String> ignoreProperties) {
		return marshalToBytes(obj, new PropertyFilter() {
			public boolean apply(Object source, String name, Object value) {
				return !ignoreProperties.contains(name);
			}
		});
    }
    
    public static byte[] marshalToBytes(Object obj, PropertyFilter propertyFilter) {
        SerializeWriter out = new SerializeWriter();
        try {
            JSONSerializer serializer = new JSONSerializer(out);
            serializer.getPropertyFilters().add(propertyFilter);
            serializer.write(obj);
            return out.toBytes(StandardCharsets.UTF_8);
        } finally {
            out.close();
        }
    }
    
    public static String marshalToString(Object obj) {
    	return JSON.toJSONString(obj, features); // 默认为UTF-8
    }

    public static String marshalToString2(Object obj) {
        SerializeWriter out = new SerializeWriter(features);
        try {
            JSONSerializer serializer = new JSONSerializer(out);
            // 只添加顶部注释,不在字段中添加注释
            serializer.write(obj);
            StringBuilder sb = new StringBuilder();
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                JSONField jsonField = field.getAnnotation(JSONField.class);
                if (jsonField != null && !jsonField.label().isEmpty()) {
                    sb.append("/* ").append(field.getName()).append(": ").append(jsonField.label()).append(" */\n");
                }
            }
            return sb.toString() + out.toString();
        } finally {
            out.close();
        }
    }
    
    public static String marshalToString(Object obj, SerializerFeature... features) {
        return JSON.toJSONString(obj, features); // 默认为UTF-8
    }
    
    /**
     * 可以允许指定一些过滤字段进行生成json对象
     */
	public static String marshalToString(Object obj, List<String> ignoreProperties) {
		return marshalToString(obj, new PropertyFilter() {
			public boolean apply(Object source, String name, Object value) {
				return !ignoreProperties.contains(name);
			}
		});
	}
    //
    public static String marshalToString(Object obj, PropertyFilter propertyFilter) {
        SerializeWriter out = new SerializeWriter();
        try {
            JSONSerializer serializer = new JSONSerializer(out);
            serializer.getPropertyFilters().add(propertyFilter);
            serializer.write(obj);
            return out.toString();
        } finally {
            out.close();
        }
    }
    
    public static <T> T unmarshalFromString(String json, Class<T> targetClass) {
        // 默认为UTF-8
        return JSON.parseObject(json, targetClass);
    }

    public static <T> T unmarshalFromString(String json, TypeReference<T> type) {
        // 默认为UTF-8
        return JSON.parseObject(json, type);
    }

    public static <T> T unmarshalFromBytes(byte[] bytes, Class<T> targetClass) {
        return JSON.parseObject(bytes, targetClass);
    }
    
    public static <T> T unmarshalFromBytes(byte[] bytes, TypeReference<T> type) {
        return unmarshalFromBytes(bytes, type.getType());
    }

    public static <T> T unmarshalFromBytes(byte[] bytes, Type type) {
        return JSON.parseObject(bytes, type);
    }

    public static void removeKeyRecursively(Map<String, Object> map, String keyToRemove) {
        map.remove(keyToRemove);

        for (String key : new ArrayList<>(map.keySet())) {
            Object value = map.get(key);
            if (value instanceof Map) {
                removeKeyRecursively((Map<String, Object>) value, keyToRemove);
            } else if (value instanceof List) {
                for (Object item : (List<?>) value) {
                    if (item instanceof Map) {
                        removeKeyRecursively((Map<String, Object>) item, keyToRemove);
                    }
                }
            }
        }
    }

    public static boolean containsKeyRecursively(Map<String, Object> map, String keyToFind) {
        if (map.containsKey(keyToFind)) {
            return true;
        }
        for (String key : map.keySet()) {
            Object value = map.get(key);
            if (value instanceof Map) {
                if (containsKeyRecursively((Map<String, Object>) value, keyToFind)) {
                    return true;
                }
            } else if (value instanceof List) {
                for (Object item : (List<?>) value) {
                    if (item instanceof Map) {
                        if (containsKeyRecursively((Map<String, Object>) item, keyToFind)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}